// 我们从二叉树的根节点 root 开始进行深度优先搜索。

// 在遍历中的每个节点处，我们输出 D 条短划线（其中 D 是该节点的深度），然后输出该节点的值。（如果节点的深度为 D，则其直接子节点的深度为 D + 1。根节点的深度为 0）。

// 如果节点只有一个子节点，那么保证该子节点为左子节点。

// 给出遍历输出 S，还原树并返回其根节点 root。

//  

// 示例 1：



// 输入："1-2--3--4-5--6--7"
// 输出：[1,2,5,3,4,6,7]
// 示例 2：



// 输入："1-2--3---4-5--6---7"
// 输出：[1,2,5,3,null,6,null,4,null,7]
// 示例 3：



// 输入："1-401--349---90--88"
// 输出：[1,401,null,349,88,90]
//  

// 提示：

// 原始树中的节点数介于 1 和 1000 之间。
// 每个节点的值介于 1 和 10 ^ 9 之间。


#include <string>

using namespace std;

// Definition for a binary tree node.
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    TreeNode* recoverFromPreorder(string S) {
        stack<TreeNode*> path{};
        int pos{0};
        int n = S.size();
        while (pos < n) {
            int level{0}; // 当前节点的深度
            while (S[pos] == '-') {
                ++level;
                ++pos;
            }

            int value{0}; // 当前节点的值
            while (pos < n && isdigit(S[pos])) {
                value = value * 10 + (S[pos] - '0');
                ++pos;
            }
            TreeNode* node = new TreeNode(value);

            // 当前节点为 T，上一个节点为 S，那么实际上只有两种情况：
            //     T 是 S 的左子节点；
            //     T 是根节点到 S 这一条路径上（不包括 S）某一个节点的右子节点。
            if (level == path.size()) {
                if (!path.empty()) {
                    path.top()->left = node;
                }
            } else {
                while (level != path.size()) {
                    path.pop();
                }
                path.top()->right = node;
            }
            path.push(node);
        }
        
        while (path.size() > 1) { // 只留下栈底的节点
            path.pop();
        }
        return path.top();
    }
};